package com.xplay.xpocker.room.mahjong.action;

import com.xplay.xpocker.constant.ConstantDict;
import com.xplay.xpocker.constant.MessageNoticeEnum;
import com.xplay.xpocker.dvo.GameRuMahjongUserState;
import com.xplay.xpocker.entity.GameRuMahjongLogs;
import com.xplay.xpocker.entity.GameRuMahjongOpenDeal;
import com.xplay.xpocker.room.RoomInfoTL;
import com.xplay.xpocker.room.mahjong.AbstractMahjongMessageStrategy;
import com.xplay.xpocker.room.mahjong.AbstractIsolationEventStrategy;
import com.xplay.xpocker.room.mahjong.constant.MKey;
import com.xplay.xpocker.room.mahjong.dto.MahjongActionEnum;
import com.xplay.xpocker.room.mahjong.dto.MahjongMessage;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomInfo;
import com.xplay.xpocker.room.mahjong.dto.MahjongRoomRule;
import com.xplay.xpocker.room.message.MessageContent;
import com.xplay.xpocker.room.message.MessageContentFactory;
import com.xplay.xpocker.room.message.MessageToClient;
import com.xplay.xpocker.room.message.MessageType;
import com.xplay.xpocker.service.gaming.GameRuMahjongOpenDealService;
import com.xplay.xpocker.util.Assertion;

import com.xplay.xpocker.dvo.AbstractRoom;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class BarAction extends AbstractMahjongMessageStrategy<AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs>, MahjongMessage> {
    @Autowired
    private GameRuMahjongOpenDealService gameRuUserOpenDealService;

    @Override
    protected String strategyName() {
        return MahjongActionEnum.BAR_CARD.getAction();
    }

    // TODO 碰牌需要判断有没有人要胡牌 杠牌优先级低于胡牌
    @Override
    public boolean doMessage(AbstractRoom<MahjongRoomRule, MahjongRoomInfo, GameRuMahjongLogs> roomInfo, MahjongMessage messageInfo) {
        MahjongRoomInfo gameInfo = roomInfo.getGameInfo();
        List<Integer> barCardArray = new ArrayList<>();
        GameRuMahjongUserState currentUser = gameInfo.getCurrentUser();
        // 检测房间中其他玩家是不是有胡的
        if (checkWaitCompletedExistsAction(MahjongActionEnum.HU)) {
            currentUser.saveNextAction(MahjongActionEnum.BAR_CARD, messageInfo);
            notifyUserActionUpdate(currentUser, 0);
            return false;
        }
        if (currentUser.allHandCards().size() % 3 == 2) {
            List<Integer> mingBar = checkUserMingBar(currentUser);
            List<Integer> darkBar = checkUserDarkBar(currentUser);
            barCardArray.addAll(mingBar);
            barCardArray.addAll(darkBar);
            Assertion.isTrue(barCardArray.size() > 1 && gameInfo.getExportCard() == null, "杠牌不明确，请确定数据。");
        } else {
            // 这是别个出的牌
            barCardArray.add(gameInfo.getExportCard());
            GameRuMahjongUserState exportUser = getUserByUidOrSeq(gameInfo.getExportUserId(), null);
            exportUser.setExportCards(exportUser.deleteLastCard(exportUser.getExportCards()));
        }
        //  如果是成麻将 这里也要积分
        Assertion.isEmpty(barCardArray, "不具备杠牌条件。");
        Integer barCard = barCardArray.get(0);
        if (messageInfo.getCardCode() != null && barCardArray.contains(messageInfo.getCardCode())) {
            barCard = messageInfo.getCardCode();
        }
        GameRuMahjongOpenDeal userOpenDeal = currentUser.getOpenDealByCard(barCard);
        userOpenDeal.setTargetUserSeq(null);
        userOpenDeal.setTargetUserId(null);
        userOpenDeal.setSourceUserId(currentUser.getUserId());
        userOpenDeal.setSourceUserSeq(currentUser.getSeq());
        log.debug("房间号:{},用户:{},执行杠牌：{}", roomInfo.getCode(), currentUser.getUsername(), barCard);
        //如果这张牌在手上大于3个
        /**
         * @type 1 碰牌,2 暗杠, 3 明杠 , 4 点杠
         */
        int currentCardCount = currentUser.checkTally(barCard);
        if (currentCardCount == ConstantDict.Mahjong.HAND_FOUR_COUNT) {
            // 手上有四个的时候  按杠
            userOpenDeal.setType(2);
        } else if (currentCardCount == ConstantDict.Mahjong.HAND_THREE_COUNT) {
            // 手上有三个的时候  点杠
            userOpenDeal.setTargetUserSeq(gameInfo.getExportUserSeq());
            userOpenDeal.setTargetUserId(gameInfo.getExportUserId());
            userOpenDeal.setType(4);
        } else if (currentCardCount == ConstantDict.Mahjong.HAND_ONE_COUNT) {
            userOpenDeal.setType(3);
            if (currentUser.getCompletedData() == null) {
                gameInfo.setExportUserId(currentUser.getUserId());
                gameInfo.setExportCard(barCard);
                boolean huAction = AbstractIsolationEventStrategy.getSettlementStrategy(roomInfo.getType())
                        .exportCardActionCheck(currentUser, barCard, roomInfo);
                if (huAction) {
                    currentUser.saveNextAction(MahjongActionEnum.BAR_CARD, messageInfo);
                    return false;
                }
            } else {
                currentUser.cleanNextAction();
            }
        }
        currentUser.removeCardAll(barCard);
        userOpenDeal.setRoomId(roomInfo.getGameInfo().getRoomId());
        userOpenDeal.setCard(barCard);
        currentUser.addOpenDeal(userOpenDeal);
        currentUser.setCompletedData(null);
        // 调用结算事件
        AbstractIsolationEventStrategy.getSettlementStrategy(roomInfo.getType())
                .settlementBar(currentUser, getUserByUidOrSeq(userOpenDeal.getTargetUserId(), null)
                        , userOpenDeal.getType(), barCard, roomInfo);
        // 构建消息通知
        List<MessageContent<MessageToClient>> messageList = MessageContentFactory.
                init(roomInfo.getCode(), MessageType.ACTION.getType(), currentUser.getUserId(), MessageNoticeEnum.ALL)
                .multi(MKey.exeActionUid, currentUser.getUserId(),
                        MKey.sourceBySeq, userOpenDeal.getTargetUserSeq(),
                        MKey.cardCode, userOpenDeal.getCard(),
                        MKey.cardType, userOpenDeal.getType(),
                        MKey.type, MahjongActionEnum.BAR_CARD.getAction())
                .send().getMessageList();
        RoomInfoTL.addMessageToClient(messageList);
        dealCard(currentUser.getSeq(), false);
        return true;
    }

}
